package pl.edu.mimuw.irs.rcp.controller.editor.workflow.command;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import pl.edu.mimuw.irs.core.model.design.net.IRSNode;
import pl.edu.mimuw.irs.core.model.design.net.IRSNodeCopier;
import pl.edu.mimuw.irs.core.model.design.net.refinement.Refinement;
import pl.edu.mimuw.irs.core.model.petrinet.Arc;
import pl.edu.mimuw.irs.core.model.petrinet.Net;

public class OverwriteNodeCommand extends IRSNodeCommand {

	// *** Attributes

	private IRSNode source;
	private IRSNode oldNode;
	private Refinement oldFragmentation;
	private List<IRSNode> oldChildren;
	private IRSNode newNode;
	private Refinement newFragmentation;
	private List<IRSNode> newChildren;
	public IRSNode getSource() {
		return source;
	}
	public IRSNode getOldNode() {
		return oldNode;
	}
	public List<IRSNode> getOldChildren() {
		return oldChildren;
	}
	public IRSNode getNewNode() {
		return newNode;
	}
	public List<IRSNode> getNewChildren() {
		return newChildren;
	}
	
	// *** Constructors
	
	public OverwriteNodeCommand(IRSNode source, IRSNode target) {
		super(target);
//		this.source = source.getCopier().copy(IRSNodeCopier.OMIT_NET_ASSIGNMENT);
//		newNode = source.getCopier().copy(IRSNodeCopier.OMIT_NET_ASSIGNMENT | IRSNodeCopier.SHALLOW);
//		newFragmentation = source.getRefinement();
//		oldFragmentation = getNode().getRefinement();
//		oldNode = source.getCopier().copy(IRSNodeCopier.OMIT_NET_ASSIGNMENT | IRSNodeCopier.SHALLOW);
//		oldChildren = new ArrayList<IRSNode>(getNode().getChildren());
		
	}
	
	// *** Methods

	@Override
	protected void performExecute() {
		/* We assume all connected nodes are in the same net */
//		
//		removeChildrenFromNet(getNode().getNet(), getNode());
//		if (newChildren == null) {
//			//newChildren = new ArrayList<IRSNode>(getSource().getChildren());
//			//getNode().setChildren(newChildren, newFragmentation);
//			getSource().getCopier().copyTo(getNode());
//			newChildren = new ArrayList<IRSNode>(getNode().getChildren());
//		} else {
//			Set<Arc> restoredArcs = new LinkedHashSet<Arc>();
//			restoreDetached(newChildren, restoredArcs);
//			getNode().setChildren(newChildren, newFragmentation);
//		}
//		newNode.getCopier().copyAttributesTo(getNode());
//		addChildrenToNet(getNode().getNet(), getNode());
	}
	
	@Override
	protected void performUndo() {
		/* We assume all connected nodes are in the same net */
		
//		removeChildrenFromNet(getNode().getNet(), getNode());
//		Set<Arc> restoredArcs = new LinkedHashSet<Arc>();
//		restoreDetached(oldChildren, restoredArcs);
//		getNode().setChildren(oldChildren, oldFragmentation);
//		oldNode.getCopier().copyAttributesTo(getNode());
//		addChildrenToNet(getNode().getNet(), getNode());
	}
//
//	private void addChildrenToNet(Net net, IRSNode node) {
//		for (IRSNode child : node.getChildren()) {
//			net.addNode(child);
//			addChildrenToNet(net, child);
//		}
//	}
//
//	private void removeChildrenFromNet(Net net, IRSNode node) {
//		for (IRSNode child : node.getChildren()) {
//			net.removeNode(child);
//			removeChildrenFromNet(net, child);
//		}
//	}
//	
//	private void restoreDetached(List<IRSNode> children, 
//			Set<Arc> restoredArcs) {
//		Net net = getNode().getNet();
//		
//		/*
//		 * To restore whole group of nodes we have to add them back to the net, 
//		 * as well as their arcs. It is important that during detach all children
//		 * persisted and arcs were removed only from one side. However arc still 
//		 * knows what Place and Transition it was connecting.
//		 */
//		for (IRSNode node : children) {
//			if (!node.isDetached()) continue;
//			node.setDetached(false);
//			
//			if (net != null) net.addNode(node);
//			
//			/* 
//			 * We pass sets because we want to restore every arc exactly
//			 * once.
//			 */
//			restoreArcs(node, restoredArcs);
//			restoreDetached(node.getChildren(), restoredArcs);
//		}
//	}
//
//	private void restoreArcs(IRSNode node,
//			Set<Arc> restoredArcs) {
//		
//		for (Arc arc : node.getIncomingArcs()) {
//			/*
//			 * We skip arc if it has already been restored.
//			 */
//			if (restoredArcs.contains(arc)) continue;
//			if (node.getNet() != null) node.getNet().addArc(arc);
//			arc.getSource().addArc(arc);
//			restoredArcs.add(arc);
//		}
//		for (Arc arc : node.getOutgoingArcs()) {
//			if (restoredArcs.contains(arc)) continue;
//			if (node.getNet() != null) node.getNet().addArc(arc);
//			arc.getTarget().addArc(arc);
//			restoredArcs.add(arc);
//		}
//	}
}
